﻿using System.Windows.Input;
using WhiteFlow.DevTrackingTool.Common.Contracts;
using WhiteFlow.DevTrackingTool.UI.Models;
using WhiteFlow.Wpf.Common.Commands;

namespace WhiteFlow.DevTrackingTool.UI.ViewModels
{
    /// <summary>
    /// The ViewModel that manages and manipulates a task list.
    /// </summary>
    public class TasksListViewModel : WorksheetChildViewModelBase
    {
        #region Constants

        public const string SelectedTaskPropertyName = "SelectedTask";

        public const string SelectedTaskIndexPropertyName = "SelectedTaskIndex";

        #endregion

        #region Fields

        private TaskExecution selectedTask;

        private int selectedTaskIndex;

        private ICommand startTrackingForCurrentDayCommand;

        private ICommand addTaskCommand;

        private ICommand insertTaskCommand;

        private ICommand deleteSelectedTaskCommand;

        private ICommand clearTrackingCommand;

        #endregion

        #region Commands

        /// <summary>
        /// Gets the command to start adding tracking data for current day.
        /// </summary>
        public ICommand StartTrackingForCurrentDayCommand
        {
            get
            {
                if (startTrackingForCurrentDayCommand == null)
                {
                    startTrackingForCurrentDayCommand = new DelegateCommand(
                        StartTrackingForCurrentDay,
                        CanStartTrackingForCurrentDay);
                }

                return startTrackingForCurrentDayCommand;
            }
        }

        /// <summary>
        /// Gets the command to add a task to the tasks list.
        /// </summary>
        public ICommand AddTaskCommand
        {
            get
            {
                if (addTaskCommand == null)
                {
                    addTaskCommand = new DelegateCommand(
                        AddTask,
                        CanAddTask);
                }

                return addTaskCommand;
            }
        }

        /// <summary>
        /// Gets the command to insert a task to the specified position in tasks list.
        /// </summary>
        public ICommand InsertTaskCommand
        {
            get
            {
                if (insertTaskCommand == null)
                {
                    insertTaskCommand = new DelegateCommand(
                        InsertTask,
                        CanInsertTask);
                }

                return insertTaskCommand;
            }
        }

        /// <summary>
        /// Gets the command to delete the selected task from the tasks list.
        /// </summary>
        public ICommand DeleteSelectedTaskCommand
        {
            get
            {
                if (deleteSelectedTaskCommand == null)
                {
                    deleteSelectedTaskCommand = new DelegateCommand(
                        DeleteSelectedTask,
                        CanDeleteSelectedTask);
                }

                return deleteSelectedTaskCommand;
            }
        }

        /// <summary>
        /// Gets the command to clear tracking data for current day.
        /// </summary>
        public ICommand ClearTrackingCommand
        {
            get
            {
                if (clearTrackingCommand == null)
                {
                    clearTrackingCommand = new DelegateCommand(
                        ClearTracking,
                        CanClearTracking);
                }

                return clearTrackingCommand;
            }
        }

        #endregion

        #region Properties

        public TaskExecution SelectedTask
        {
            get { return selectedTask; }
            set
            {
                selectedTask = value;
                OnPropertyChanged(SelectedTaskPropertyName);
            }
        }

        public int SelectedTaskIndex
        {
            get { return selectedTaskIndex; }
            set
            {
                selectedTaskIndex = value;
                OnPropertyChanged(SelectedTaskIndexPropertyName);
            }
        }

        #endregion

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="TasksListViewModel"/> class.
        /// </summary>
        /// <param name="ownerWorksheetViewModel">The <see cref="WorksheetViewModel"/> instance that owns this instance.</param>
        public TasksListViewModel(WorksheetViewModel ownerWorksheetViewModel) : base(ownerWorksheetViewModel) { }

        #endregion

        #region Commands Implementations

        private void StartTrackingForCurrentDay()
        {
            TrackingDay trackingDay = new TrackingDay() { CalendarDay = OwnerWorksheetViewModel.SelectedDay };
            trackingDay.SetOwner(OwnerWorksheetViewModel.Worksheet);

            int index = 0;
            if (OwnerWorksheetViewModel.Worksheet.Days.Count > 0)
            {
                while (
                    index < OwnerWorksheetViewModel.Worksheet.Days.Count &&
                    trackingDay.CalendarDay.CompareTo(OwnerWorksheetViewModel.Worksheet.Days[index].CalendarDay) > 0)
                {
                    index++;
                }
            }

            OwnerWorksheetViewModel.Worksheet.Days.Insert(index, trackingDay);
            OwnerWorksheetViewModel.SelectedTrackingDay = trackingDay;
        }

        private bool CanStartTrackingForCurrentDay()
        {
            return (ownerWorksheetViewModel.SelectedTrackingDay == null);
        }

        private void AddTask()
        {
            TaskExecution task = new TaskExecution(ownerWorksheetViewModel.SelectedTrackingDay);
            ownerWorksheetViewModel.SelectedTrackingDay.ExecutedTasks.Add(task);
        }

        private bool CanAddTask()
        {
            return (
                ownerWorksheetViewModel.SelectedTrackingDay != null &&
                ownerWorksheetViewModel.SelectedTrackingDay.ExecutedTasks != null);
        }

        private void InsertTask()
        {
            TaskExecution task = new TaskExecution(ownerWorksheetViewModel.SelectedTrackingDay);
            ownerWorksheetViewModel.SelectedTrackingDay.ExecutedTasks.Insert(SelectedTaskIndex, task);
        }

        private bool CanInsertTask()
        {
            return (CanAddTask() && (SelectedTaskIndex != -1));
        }

        private void DeleteSelectedTask()
        {
            int index = OwnerWorksheetViewModel.SelectedTrackingDay.ExecutedTasks.IndexOf(SelectedTask);

            if (index != -1)
            {
                OwnerWorksheetViewModel.SelectedTrackingDay.ExecutedTasks.RemoveAt(index);
            }
        }

        private bool CanDeleteSelectedTask()
        {
            return (SelectedTask != null);
        }

        private void ClearTracking()
        {
            OwnerWorksheetViewModel.Worksheet.Days.Remove(OwnerWorksheetViewModel.SelectedTrackingDay);
            OwnerWorksheetViewModel.SelectedTrackingDay = null;
        }

        private bool CanClearTracking()
        {
            return (ownerWorksheetViewModel.SelectedTrackingDay != null);
        }

        #endregion
    }
}